#include "main.h"

#include <stdio.h>
#include <string.h>

#include "adc.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
#include "project.h"

UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
TIM_HandleTypeDef htim2;
ProjectTypeDef project;

uint8_t usart1RxBuf[1] = {0};
uint8_t usart1Ready = 0;
uint8_t serviceReceived[256];
uint8_t rxIndex = 0;
uint8_t cmdReceived = 0;

void SystemClock_Config(void);

void processCommand(const char *cmd);

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_ADC1_Init();
    MX_USART1_UART_Init();
    MX_USART2_UART_Init();
    HAL_UART_Receive_IT(&huart1, usart1RxBuf, 1);

    ProjectInit(&project);
    Hardware_lightInit(&hadc1);
    Hardware_esp01sReset();
    HAL_Delay(2000);
    Hardware_esp01sInit();
    if (!Hardware_esp01sTest()) {
        Error_Handler();
    }
    if (!Hardware_esp01sConnectWiFi()) {
        Error_Handler();
    }

    char equipRunPath[1 << 6];
    sprintf(equipRunPath, "%s/%llu",SERVER_PATH_RUN, project.equipId);
    Hardware_esp01sSendHttpGet(equipRunPath, NULL);

    char json[1 << 9] = {0};
    while (1) {
        if (usart1Ready) {
            usart1Ready = 0;
            if (usart1RxBuf[0] == '1') {
                Hardware_motorOpen(&project);
                ProjectManualControl(&project);
                project.autoControl = false;
            } else if (usart1RxBuf[0] == '0') {
                Hardware_motorClose(&project);
                ProjectManualControl(&project);
                project.autoControl = false;
            } else if (usart1RxBuf[0] == '2') {
                Hardware_run(&project);
            } else if (usart1RxBuf[0] == '3') {
                Hardware_stop(&project);
            }
        }

        if (!project.run) {
            HAL_Delay(2000);
            continue;
        }
        ProjectInitSensorParam(&project);

        // 数据检测
        Hardware_dht11GetData(&project);
        if (!project.dht11Suc && project.dht11ErrCount++ > COMMON_DHT11_ERR_COUNT)
            project.dht11NormalOper = false;
        Hardware_lightReadPercent(&project);
        if (!project.lightSuc && project.lightErrCount++ > COMMON_LIGHT_ERR_COUNT)
            project.lightNormalOper = false;

        // 行为驱动
        if (ProjectAutoControl(&project)) {
            if ((project.lightSuc && project.lightPercent > COMMON_LIGHT_PERCENT_CRITICAL) ||
                (project.dht11Suc && (project.dht11Humidity < COMMON_DHT11_HUMIDITY_CRITICAL &&
                                      project.dht11Humidity > COMMON_DHT11_TEMPERATURE_CRITICAL))
            ) {
                Hardware_motorOpen(&project);
            } else {
                Hardware_motorClose(&project);
            }
        }

        // 数据上传
        ProjectDataAssemble(&project, json, 1 << 9);
        Hardware_esp01sSendHttpPost(SERVER_PATH_DATA_UPLOAD, json);
        HAL_UART_Transmit(&huart1, json, strlen(json), HAL_MAX_DELAY);
        HAL_Delay(2000);
    }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == USART1) {
        HAL_UART_Receive_IT(&huart1, usart1RxBuf, 1);
        usart1Ready = 1;
        char usart1rxCmd[32];
        snprintf(usart1rxCmd, 32, "input: %c\r\n", usart1RxBuf[0]);
        HAL_UART_Transmit(&huart1, usart1rxCmd, 10, 100);
    } else if (huart->Instance == USART2) {
        if (serviceReceived[rxIndex] == '\n' || rxIndex >= sizeof(serviceReceived) - 1) {
            cmdReceived = 1;
            serviceReceived[rxIndex] = '\0';
        } else {
            rxIndex++;
            HAL_UART_Receive_IT(&huart2, &serviceReceived[rxIndex], 1);
        }
    }
}

void processCommand(const char *cmd) {
    if (strstr(cmd, "GET /") != NULL) {
        const char *cmdStart = strstr(cmd, "GET /");
        if (cmdStart != NULL) {
            cmdStart += 5; // 跳过"GET /"
            if (strncmp(cmdStart, "run", 3) == 0) {
                Hardware_run(&project);
            } else if (strncmp(cmdStart, "stop", 4) == 0) {
                Hardware_stop(&project);
            } else if (strncmp(cmdStart, "open", 4) == 0) {
                Hardware_motorOpen(&project);
                ProjectManualControl(&project);
            } else if (strncmp(cmdStart, "close", 5) == 0) {
                Hardware_motorClose(&project);
                ProjectManualControl(&project);
            }
        }
    }
}


void SystemClock_Config(void) {
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
        Error_Handler();
    }

    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                  | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
        Error_Handler();
    }
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
    PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV2;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
        Error_Handler();
    }
}

void Error_Handler(void) {
    __disable_irq();
    while (1) {
    }
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
